#include "VariableParameter.h"

namespace czj {
namespace util {

VariableParameter::VariableParameter(const char *_describe, bool _nullable)
		: Parameter(_describe), nullable_(_nullable), null_(true), hints_(), keys_(), expressions_(), defaults_(), value_() {
}

VariableParameter::~VariableParameter() {
}

Parameter::Type VariableParameter::getType() const {
	return VARIABLE;
}

bool VariableParameter::isNullable() const {
	return nullable_;
}

bool VariableParameter::isNull() const {
	return null_;
}

const std::list<std::string> &VariableParameter::getHints() const {
	return hints_;
}

bool VariableParameter::bindKey(const char *_key, const char *_hint) {
	if (!keys_.insert(_key).second) {
		return false;
	}
	if (_hint != nullptr && _hint[0] != '\0') {
		hints_.push_back(std::string(_key).append(" <").append(_hint).append(">"));
	}
	else {
		hints_.push_back(std::string(_key));
	}
	return true;
}

bool VariableParameter::matchKey(const char *_key, const char *_value) {
	if (keys_.find(_key) != keys_.cend()) {
		null_ = false;
		value_ = _value;
		return true;
	}
	return false;
}

bool VariableParameter::bindExpression(const char *_key, const char *_operator, const char *_hint, const char *_default) {
	expressions_.push_back(std::string(_key).append(_operator));
	if (_default != nullptr) {
		defaults_[_key] = _default;
		if (_hint != nullptr && _hint[0] != '\0') {
			hints_.push_back(std::string(_key).append("[").append(_operator).append(_hint).append("(").append(_default).append(")]"));
		}
		else {
			hints_.push_back(std::string(_key).append("[").append(_operator).append("(").append(_default).append(")]"));
		}
	}
	else {
		if (_hint != nullptr && _hint[0] != '\0') {
			hints_.push_back(std::string(_key).append(_operator).append("<").append(_hint).append(">"));
		}
		else {
			hints_.push_back(std::string(_key).append(_operator));
		}
	}
	return true;
}

bool VariableParameter::matchExpression(const char *_expression) {
	auto const &iterator = defaults_.find(_expression);
	if (iterator != defaults_.cend()) {
		null_ = false;
		value_ = iterator->second;
		return true;
	}
	for (auto const &expression : expressions_) {
		if (expression.compare(0, expression.length(), _expression, expression.length()) == 0) {
			null_ = false;
			value_ = _expression + expression.length();
			return true;
		}
	}
	return false;
}

const std::string &VariableParameter::getValue() const {
	return value_;
}

} // util
} // czj
